package cn.hn3l.untils;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * Created by Wang Weiwei on 2016/8/22.
 * @version 1.0 BATA
 *
 */
@WebServlet(name = "captcha",urlPatterns = {"/captcha"})
public class Captcha extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        OutputStream outputStream = response.getOutputStream();
        BufferedImage bufferedImage = new BufferedImage(180, 50 ,BufferedImage.TYPE_INT_RGB);
        //设置服务器回应头
        response.setHeader("Pragma","No-cache");
        response.setHeader("Cache-Control","no-cache");
        response.setDateHeader("Expires", 0);
        //表明生成的响应是图片
        response.setContentType("image/jpeg");
        //绘制验证码
        int sResult = drawCaptcha(bufferedImage);
//        打印测试数据
        System.out.println(sResult);
        request.getSession().setAttribute("sResult", sResult);
        //通过ImageIO将image写入到服务器响应输出流中
        ImageIO.write(bufferedImage, "JPEG",outputStream);
    }

    private int drawCaptcha(BufferedImage bufferedImage) {
        Graphics2D graphics2D = bufferedImage.createGraphics();
        //画背景
        graphics2D.setColor(getRandomColor(200, 250));
        graphics2D.fillRect(0, 0,200,50);
        int width = 200;
        int height = 50;
        //画干扰线
        grawRandomLine(width, height, graphics2D);
        //画字符以及符号
        return drawNum(getNums(),graphics2D);
    }

    /**画出验证码干扰线*/
    private void grawRandomLine(int width, int height, Graphics2D graphics2D) {
        //画200条短线
        for (int i = 0; i < 200; i++) {
            graphics2D.setStroke(new BasicStroke(random.nextInt(3)));
            graphics2D.setColor(getRandomColor(0, 255));
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x2 = random.nextInt(30);
            int y2 = random.nextInt(20);
            graphics2D.drawLine(x, y, x + x2, y + y2);
        }
        //画5条长线
        for (int i = 0; i < 5; i++) {
            graphics2D.setStroke(new BasicStroke(random.nextInt(5)));
            graphics2D.setColor(getRandomColor(80, 120));
            int x = random.nextInt(width - 50);
            int y = random.nextInt(height);
            int x2 = 50;
            int y2 = random.nextInt(20);
            graphics2D.drawLine(x, y, x + x2, y + y2);
        }
        for (int j = 0; j < 200; j++) {
            graphics2D.setStroke(new BasicStroke(random.nextInt(4)));
            graphics2D.setColor(getRandomColor(180, 230));
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            graphics2D.drawLine(x, y, x2, y2);
        }

    }

    /**画数字*/
    private int drawNum(int[] nums, Graphics2D graphics2D) {
        //获取操作符
        char[] sysbols = {'+', '-'};
        int[] symbol = getSymbol(nums.length);
        int beginPointX = 10;
        int beginPointY = 20;
        for (int i = 0; i < nums.length; i++) {

            String numStr = String.valueOf(nums[i]);
            for (int j = 0; j < numStr.length(); j++) {
                setGraphicProperty(graphics2D);
                graphics2D.drawString(String.valueOf(numStr.charAt(j)),
                        beginPointX + random.nextInt(10), beginPointY + random.nextInt(10));
                beginPointX += 20;
                setGraphicProperty(graphics2D);
            }
            if(i < symbol.length){
                graphics2D.drawString(String.valueOf(sysbols[symbol[i] - 1]),
                        beginPointX + random.nextInt(10), beginPointY + random.nextInt(10));
                beginPointX += 20;
            }else {
                graphics2D.drawString(String.valueOf("="),
                        beginPointX + random.nextInt(10), beginPointY + random.nextInt(10));
                beginPointX += 20;
            }

        }
        graphics2D.drawString(String.valueOf("?"),
                beginPointX + random.nextInt(10), beginPointY + random.nextInt(10));
        return getValue(nums, symbol);
    }

    /**获取验证码结果*/
    private int getValue(int[] nums, int[] symbol) {
        int temp = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i == 0){
                temp = nums[i];
            }else {
                switch (symbol[i - 1]){
                    case 1:
                        temp += nums[i];
                        break;
                    case 2:
                        temp -= nums[i];
                        break;
                }
            }
        }
        return temp;
    }

    private void setGraphicProperty(Graphics2D graphics2D) {
        graphics2D.setFont(setFont(random.nextInt(4)));
        graphics2D.setColor(getRandomColor(50,100));
        graphics2D.setStroke(new BasicStroke(random.nextInt(4)));
    }

    /**获取操作符
     * 1:'+'
     * 2:'-'*/
    private int[] getSymbol(int length) {
        int[] symbol = new int[length - 1];
        for (int i = 0; i < symbol.length; i++) {
            symbol[i] = random.nextInt(2) + 1;
        }
        return symbol;
    }

    /**获取随机颜色
     * @param fc 前景色
     * @param bc 背景色
     * @return  具体返回颜色为rgb颜色，其值在fc和bg之间随机*/
    private Color getRandomColor(int fc, int bc) {
        int difference = bc - fc;
        int red = random.nextInt(difference) + fc;
        int green = random.nextInt(difference) + fc;
        int blue = random.nextInt(difference) + fc;
        return new Color(red, green,blue);
    }

    //随机数控制
    private Random random = new Random();

    private int[] getNums() {
        //共有size个数()
        int size = random.nextInt(2) + 2;
        int[] nums = new int[size];
        for (int i = 0; i < size; i++) {
            nums[i] = random.nextInt(13);
        }
        return nums;
    }

    /**随机获取四种默认字体中的某种字体*/
    public Font setFont(int font) {
        Font[] fonts = new Font[4];
        fonts[0] = new Font("Times New Roman", Font.PLAIN, 30);
        fonts[1] = new Font("Times New Roman", Font.BOLD, 28);
        fonts[2] = new Font("Times New Roman", Font.ITALIC, 30);
        fonts[3] = new Font("Times New Roman", Font.PLAIN, 28);
        return fonts[font];
    }
}
